﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;

namespace UIControls
{
    public interface IQueryAmbient
    {
        // Summary:
        //     Queries for whether a specified named property can be considered ambient
        //     in the current scope.
        //
        // Parameters:
        //   propertyName:
        //     The name of the property to check for ambience state.
        //
        // Returns:
        //     true if the requested property can be considered ambient; otherwise, false.
        bool IsAmbientPropertyAvailable(string propertyName);
    }

    public class Drag : Border
    {
        public FrameworkElement ContainerElement
        {
            get { return (FrameworkElement)GetValue(ContainerElementProperty); }
            set { SetValue(ContainerElementProperty, value); }
        }

        public static readonly DependencyProperty ContainerElementProperty =
            DependencyProperty.Register("ContainerElement", typeof(FrameworkElement), typeof(Drag));



        /// <summary>
        /// Gets/Sets TargetElement
        /// 操作目标对象
        /// </summary>
        public FrameworkElement TargetElement
        {
            get { return (FrameworkElement)GetValue(TargetElementProperty); }
            set { SetValue(TargetElementProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TargetElement.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TargetElementProperty =
            DependencyProperty.Register("TargetElement", typeof(FrameworkElement), typeof(Drag));


        public FrameworkElement Box
        {
            get { return (FrameworkElement)GetValue(BoxProperty); }
            set { SetValue(BoxProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TargetElement.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BoxProperty =
            DependencyProperty.Register("Box", typeof(FrameworkElement), typeof(Drag));


        private bool isDown;
        private Point startPoint;


        public Drag()
        {
            this.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(Drag_PreviewMouseLeftButtonDown);
            this.PreviewMouseMove += new System.Windows.Input.MouseEventHandler(Drag_PreviewMouseMove);
            this.PreviewMouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(Drag_PreviewMouseLeftButtonUp);
        }

        void Drag_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.Source.GetType() == typeof(Drag))
            {

                this.isDown = true;
                this.startPoint = e.GetPosition(e.Source as UIElement);
                this.CaptureMouse();

                if (this.Box != null && this.Box is ListBox && this.TargetElement is ListBoxItem)
                {
                    ((ListBox)this.Box).SelectedItem = this.TargetElement.DataContext;
                }
                e.Handled = true;
            }
        }

        void Drag_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (this.isDown)
            {
                Point CurrentPosition = System.Windows.Input.Mouse.GetPosition(this.ContainerElement);

                double x = CurrentPosition.X - startPoint.X;
                double y = CurrentPosition.Y - startPoint.Y;

                //计算最大值和最小值
                if (x < 0) x = 0;
                if (y < 0) y = 0;

                double maxLeft = this.ContainerElement.ActualWidth - this.TargetElement.ActualWidth;
                double maxTop = this.ContainerElement.ActualHeight - this.TargetElement.ActualHeight;

                if (x > maxLeft) { x = maxLeft; }
                if (y > maxTop) { y = maxTop; }


                Canvas.SetLeft(this.TargetElement, Math.Round(x));
                Canvas.SetTop(this.TargetElement, Math.Round(y));

                e.Handled = true;
            }
        }

        void Drag_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (this.isDown)
            {
                System.Windows.Input.Mouse.Capture(null);
                //Panel.SetZIndex(this.TargetElement, 90);
                this.isDown = false;
                e.Handled = true;
            }
        }
    }
}
